home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / src / linux-headers-2.6.28-15 / arch / alpha / include / asm / atomic.h < prev    next >
Encoding:
C/C++ Source or Header  |  2008-12-24  |  6.4 KB  |  268 lines

  1. #ifndef _ALPHA_ATOMIC_H
  2. #define _ALPHA_ATOMIC_H
  3.  
  4. #include <asm/barrier.h>
  5. #include <asm/system.h>
  6.  
  7. /*
  8.  * Atomic operations that C can't guarantee us.  Useful for
  9.  * resource counting etc...
  10.  *
  11.  * But use these as seldom as possible since they are much slower
  12.  * than regular operations.
  13.  */
  14.  
  15.  
  16. /*
  17.  * Counter is volatile to make sure gcc doesn't try to be clever
  18.  * and move things around on us. We need to use _exactly_ the address
  19.  * the user gave us, not some alias that contains the same information.
  20.  */
  21. typedef struct { volatile int counter; } atomic_t;
  22. typedef struct { volatile long counter; } atomic64_t;
  23.  
  24. #define ATOMIC_INIT(i)        ( (atomic_t) { (i) } )
  25. #define ATOMIC64_INIT(i)    ( (atomic64_t) { (i) } )
  26.  
  27. #define atomic_read(v)        ((v)->counter + 0)
  28. #define atomic64_read(v)    ((v)->counter + 0)
  29.  
  30. #define atomic_set(v,i)        ((v)->counter = (i))
  31. #define atomic64_set(v,i)    ((v)->counter = (i))
  32.  
  33. /*
  34.  * To get proper branch prediction for the main line, we must branch
  35.  * forward to code at the end of this object's .text section, then
  36.  * branch back to restart the operation.
  37.  */
  38.  
  39. static __inline__ void atomic_add(int i, atomic_t * v)
  40. {
  41.     unsigned long temp;
  42.     __asm__ __volatile__(
  43.     "1:    ldl_l %0,%1\n"
  44.     "    addl %0,%2,%0\n"
  45.     "    stl_c %0,%1\n"
  46.     "    beq %0,2f\n"
  47.     ".subsection 2\n"
  48.     "2:    br 1b\n"
  49.     ".previous"
  50.     :"=&r" (temp), "=m" (v->counter)
  51.     :"Ir" (i), "m" (v->counter));
  52. }
  53.  
  54. static __inline__ void atomic64_add(long i, atomic64_t * v)
  55. {
  56.     unsigned long temp;
  57.     __asm__ __volatile__(
  58.     "1:    ldq_l %0,%1\n"
  59.     "    addq %0,%2,%0\n"
  60.     "    stq_c %0,%1\n"
  61.     "    beq %0,2f\n"
  62.     ".subsection 2\n"
  63.     "2:    br 1b\n"
  64.     ".previous"
  65.     :"=&r" (temp), "=m" (v->counter)
  66.     :"Ir" (i), "m" (v->counter));
  67. }
  68.  
  69. static __inline__ void atomic_sub(int i, atomic_t * v)
  70. {
  71.     unsigned long temp;
  72.     __asm__ __volatile__(
  73.     "1:    ldl_l %0,%1\n"
  74.     "    subl %0,%2,%0\n"
  75.     "    stl_c %0,%1\n"
  76.     "    beq %0,2f\n"
  77.     ".subsection 2\n"
  78.     "2:    br 1b\n"
  79.     ".previous"
  80.     :"=&r" (temp), "=m" (v->counter)
  81.     :"Ir" (i), "m" (v->counter));
  82. }
  83.  
  84. static __inline__ void atomic64_sub(long i, atomic64_t * v)
  85. {
  86.     unsigned long temp;
  87.     __asm__ __volatile__(
  88.     "1:    ldq_l %0,%1\n"
  89.     "    subq %0,%2,%0\n"
  90.     "    stq_c %0,%1\n"
  91.     "    beq %0,2f\n"
  92.     ".subsection 2\n"
  93.     "2:    br 1b\n"
  94.     ".previous"
  95.     :"=&r" (temp), "=m" (v->counter)
  96.     :"Ir" (i), "m" (v->counter));
  97. }
  98.  
  99.  
  100. /*
  101.  * Same as above, but return the result value
  102.  */
  103. static inline int atomic_add_return(int i, atomic_t *v)
  104. {
  105.     long temp, result;
  106.     smp_mb();
  107.     __asm__ __volatile__(
  108.     "1:    ldl_l %0,%1\n"
  109.     "    addl %0,%3,%2\n"
  110.     "    addl %0,%3,%0\n"
  111.     "    stl_c %0,%1\n"
  112.     "    beq %0,2f\n"
  113.     ".subsection 2\n"
  114.     "2:    br 1b\n"
  115.     ".previous"
  116.     :"=&r" (temp), "=m" (v->counter), "=&r" (result)
  117.     :"Ir" (i), "m" (v->counter) : "memory");
  118.     smp_mb();
  119.     return result;
  120. }
  121.  
  122. static __inline__ long atomic64_add_return(long i, atomic64_t * v)
  123. {
  124.     long temp, result;
  125.     smp_mb();
  126.     __asm__ __volatile__(
  127.     "1:    ldq_l %0,%1\n"
  128.     "    addq %0,%3,%2\n"
  129.     "    addq %0,%3,%0\n"
  130.     "    stq_c %0,%1\n"
  131.     "    beq %0,2f\n"
  132.     ".subsection 2\n"
  133.     "2:    br 1b\n"
  134.     ".previous"
  135.     :"=&r" (temp), "=m" (v->counter), "=&r" (result)
  136.     :"Ir" (i), "m" (v->counter) : "memory");
  137.     smp_mb();
  138.     return result;
  139. }
  140.  
  141. static __inline__ long atomic_sub_return(int i, atomic_t * v)
  142. {
  143.     long temp, result;
  144.     smp_mb();
  145.     __asm__ __volatile__(
  146.     "1:    ldl_l %0,%1\n"
  147.     "    subl %0,%3,%2\n"
  148.     "    subl %0,%3,%0\n"
  149.     "    stl_c %0,%1\n"
  150.     "    beq %0,2f\n"
  151.     ".subsection 2\n"
  152.     "2:    br 1b\n"
  153.     ".previous"
  154.     :"=&r" (temp), "=m" (v->counter), "=&r" (result)
  155.     :"Ir" (i), "m" (v->counter) : "memory");
  156.     smp_mb();
  157.     return result;
  158. }
  159.  
  160. static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
  161. {
  162.     long temp, result;
  163.     smp_mb();
  164.     __asm__ __volatile__(
  165.     "1:    ldq_l %0,%1\n"
  166.     "    subq %0,%3,%2\n"
  167.     "    subq %0,%3,%0\n"
  168.     "    stq_c %0,%1\n"
  169.     "    beq %0,2f\n"
  170.     ".subsection 2\n"
  171.     "2:    br 1b\n"
  172.     ".previous"
  173.     :"=&r" (temp), "=m" (v->counter), "=&r" (result)
  174.     :"Ir" (i), "m" (v->counter) : "memory");
  175.     smp_mb();
  176.     return result;
  177. }
  178.  
  179. #define atomic64_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
  180. #define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
  181.  
  182. #define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
  183. #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
  184.  
  185. /**
  186.  * atomic_add_unless - add unless the number is a given value
  187.  * @v: pointer of type atomic_t
  188.  * @a: the amount to add to v...
  189.  * @u: ...unless v is equal to u.
  190.  *
  191.  * Atomically adds @a to @v, so long as it was not @u.
  192.  * Returns non-zero if @v was not @u, and zero otherwise.
  193.  */
  194. static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
  195. {
  196.     int c, old;
  197.     c = atomic_read(v);
  198.     for (;;) {
  199.         if (unlikely(c == (u)))
  200.             break;
  201.         old = atomic_cmpxchg((v), c, c + (a));
  202.         if (likely(old == c))
  203.             break;
  204.         c = old;
  205.     }
  206.     return c != (u);
  207. }
  208.  
  209. #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
  210.  
  211. /**
  212.  * atomic64_add_unless - add unless the number is a given value
  213.  * @v: pointer of type atomic64_t
  214.  * @a: the amount to add to v...
  215.  * @u: ...unless v is equal to u.
  216.  *
  217.  * Atomically adds @a to @v, so long as it was not @u.
  218.  * Returns non-zero if @v was not @u, and zero otherwise.
  219.  */
  220. static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
  221. {
  222.     long c, old;
  223.     c = atomic64_read(v);
  224.     for (;;) {
  225.         if (unlikely(c == (u)))
  226.             break;
  227.         old = atomic64_cmpxchg((v), c, c + (a));
  228.         if (likely(old == c))
  229.             break;
  230.         c = old;
  231.     }
  232.     return c != (u);
  233. }
  234.  
  235. #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
  236.  
  237. #define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
  238. #define atomic64_add_negative(a, v) (atomic64_add_return((a), (v)) < 0)
  239.  
  240. #define atomic_dec_return(v) atomic_sub_return(1,(v))
  241. #define atomic64_dec_return(v) atomic64_sub_return(1,(v))
  242.  
  243. #define atomic_inc_return(v) atomic_add_return(1,(v))
  244. #define atomic64_inc_return(v) atomic64_add_return(1,(v))
  245.  
  246. #define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
  247. #define atomic64_sub_and_test(i,v) (atomic64_sub_return((i), (v)) == 0)
  248.  
  249. #define atomic_inc_and_test(v) (atomic_add_return(1, (v)) == 0)
  250. #define atomic64_inc_and_test(v) (atomic64_add_return(1, (v)) == 0)
  251.  
  252. #define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
  253. #define atomic64_dec_and_test(v) (atomic64_sub_return(1, (v)) == 0)
  254.  
  255. #define atomic_inc(v) atomic_add(1,(v))
  256. #define atomic64_inc(v) atomic64_add(1,(v))
  257.  
  258. #define atomic_dec(v) atomic_sub(1,(v))
  259. #define atomic64_dec(v) atomic64_sub(1,(v))
  260.  
  261. #define smp_mb__before_atomic_dec()    smp_mb()
  262. #define smp_mb__after_atomic_dec()    smp_mb()
  263. #define smp_mb__before_atomic_inc()    smp_mb()
  264. #define smp_mb__after_atomic_inc()    smp_mb()
  265.  
  266. #include <asm-generic/atomic.h>
  267. #endif /* _ALPHA_ATOMIC_H */
  268.